﻿using Game.ModbusHepler.Resolve;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ReactiveChannelMessaging.ModbusHepler
{
   public static class ModbusCommandParser
    {

        public static bool IsValidHex(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
                return false;
            return System.Text.RegularExpressions.Regex.IsMatch(input, @"^[0-9A-Fa-f]+$");
        }
        /// <summary>
        /// 验证Modbus CRC校验码
        /// </summary>
        public static bool VerifyModbusCRC(byte[] data)
        {
            try
            {
                if (data.Length < 4)
                    return false;

                // 计算数据部分的CRC（除去最后2个字节）
                var dataWithoutCrc = new byte[data.Length - 2];
                Array.Copy(data, 0, dataWithoutCrc, 0, data.Length - 2);

                ushort calculatedCrc = CalculateModbusCRC(dataWithoutCrc);

                // 提取报文中的CRC（低字节在前）
                ushort receivedCrc = (ushort)(data[data.Length - 2] | (data[data.Length - 1] << 8));

                return calculatedCrc == receivedCrc;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 计算Modbus CRC-16校验码
        /// </summary>
        public static ushort CalculateModbusCRC(byte[] data)
        {
            ushort crc = 0xFFFF;
            for (int pos = 0; pos < data.Length; pos++)
            {
                crc ^= (ushort)data[pos];
                for (int i = 8; i != 0; i--)
                {
                    if ((crc & 0x0001) != 0)
                    {
                        crc >>= 1;
                        crc ^= 0xA001;
                    }
                    else
                        crc >>= 1;
                }
            }
            return crc;
        }

        /// <summary>
        /// 获取期望Modbus报文长度（用于调试）
        /// </summary>
        public static string GetExpectedModbusLength(byte[] data, SendType sendType)
        {
            try
            {
                var functionCode = data[1];

                if (sendType == SendType.Request)
                {
                    switch (functionCode)
                    {
                        case 0x03:
                        case 0x04:
                        case 0x06:
                            return "8";
                        case 0x10:
                            if (data.Length >= 7)
                            {
                                var byteCount = data[6];
                                return $"{9 + byteCount}";
                            }
                            return "9+字节数";
                        default:
                            return "未知";
                    }
                }
                else // Response
                {
                    switch (functionCode)
                    {
                        case 0x03:
                        case 0x04:
                            if (data.Length >= 3)
                            {
                                var dataByteCount = data[2];
                                return $"{5 + dataByteCount}";
                            }
                            return "5+数据字节数";
                        case 0x06:
                        case 0x10:
                            return "8";
                        default:
                            return "未知";
                    }
                }
            }
            catch
            {
                return "错误";
            }
        }

        /// <summary>
        /// 验证Modbus报文长度是否符合协议规范
        /// </summary>
        public static bool ValidateModbusMessageLength(byte[] data, SendType sendType)
        {
            try
            {
                var functionCode = data[1];

                if (sendType == SendType.Request)
                {
                    // 请求报文验证
                    switch (functionCode)
                    {
                        case 0x03: // 读保持寄存器
                        case 0x04: // 读输入寄存器
                        case 0x06: // 写单个寄存器
                            return data.Length == 8; // 请求格式: [设备地址][.func][寄存器地址(2)][数量/值(2)][CRC(2)]

                        case 0x10: // 写多个寄存器
                            if (data.Length < 9)
                                return false; // 最小长度检查
                            var byteCount = data[6]; // 字节数字段
                            var expectedLength = 9 + byteCount; // 9 = 设备地址(1) + 功能码(1) + 寄存器地址(2) + 寄存器数量(2) + 字节数(1) + CRC(2)
                            return data.Length == expectedLength;

                        default:
                            return true; // 未知功能码，默认通过
                    }
                }
                else // SendType.Response
                {
                    // 响应报文验证
                    switch (functionCode)
                    {
                        case 0x03: // 读保持寄存器响应
                        case 0x04: // 读输入寄存器响应
                            if (data.Length < 5)
                                return false;
                            var dataByteCount = data[2]; // 响应中的字节数字段
                            var expectedResponseLength = 5 + dataByteCount; // 5 = 设备地址(1) + 功能码(1) + 字节数(1) + CRC(2)
                            return data.Length == expectedResponseLength;

                        case 0x06: // 写单个寄存器响应
                        case 0x10: // 写多个寄存器响应
                            return data.Length == 8; // 写功能的响应长度固定为8字节

                        default:
                            return true; // 未知功能码，默认通过
                    }
                }
            }
            catch
            {
                return false; // 发生异常时返回false
            }
        }

        /// <summary>
        /// 判断消息类型（请求或响应）
        /// </summary>
        public static SendType DetermineMessageType(byte[] data, string direction)
        {
            // 根据传输方向和数据特征判断
            if (direction == "TX")
            {
                // 发送的数据通常是请求
                return SendType.Request;
            }
            else // RX
            {
                // 接收的数据可能是响应，但需要根据数据长度和功能码判断
                var functionCode = data[1];

                // 如果是错误响应（功能码最高位为1）
                if ((functionCode & 0x80) != 0)
                {
                    return SendType.Response;
                }

                // 根据数据长度和功能码精确判断
                switch (functionCode)
                {
                    case 0x03: // 读保持寄存器
                    case 0x04: // 读输入寄存器
                               // 请求长度固定为8字节，响应长度为5+数据字节数
                        if (data.Length == 8)
                        {
                            return SendType.Request; // 读取请求
                        }
                        else if (data.Length >= 5 && data.Length == 5 + data[2])
                        {
                            return SendType.Response; // 读取响应
                        }
                        break;

                    case 0x06: // 写单个寄存器
                               // 请求和响应的长度都是8字节，难以区分，默认为响应
                        return SendType.Response;

                    case 0x10: // 写多个寄存器
                        if (data.Length == 8)
                        {
                            return SendType.Response; // 写多寄存器响应
                        }
                        else if (data.Length > 9)
                        {
                            return SendType.Request; // 写多寄存器请求
                        }
                        break;
                }

                // 默认作为请求处理
                return SendType.Request;
            }
        }

    }
}
